package solver

import (
	"math/rand"
	"time"
)

func (g *Grid) givenString() string {
	values := make([]uint8, 81)
	n := 0
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			values[n] = uint8(g.givens[i][j]) + '0'
			n++
		}
	}
	return string(values)
}

func (g *Grid) String() string {
	values := make([]uint8, 81)
	n := 0
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			values[n] = uint8(g.cells[i][j].value) + '0'
			n++
		}
	}
	return string(values)
}

func TransReplace(raw string) string {
	var digits []uint8

	digits = []uint8{'1', '2', '3', '4', '5', '6', '7', '8', '9'}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	r.Shuffle(len(digits), func(i, j int) {
		digits[i], digits[j] = digits[j], digits[i]
	})
	digits = append([]uint8{'0'}, digits...)

	out := []uint8(raw)

	for i := 0; i < len(out); i++ {
		out[i] = digits[out[i]-'0']
	}

	return string(out)
}

func padding(raw string) []uint8 {
	out := make([]uint8, 81)
	copy(out, []byte(raw))
	length := len(raw)
	for i := length; i < 81; i++ {
		out[i] = '0'
	}
	return out
}

func sliceToMatrix(s []uint8) [9][9]uint8 {
	m := [9][9]uint8{}
	n := 0
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			m[i][j] = s[n]
			n++
		}
	}
	return m
}

func matrixToSlice(m [9][9]uint8) []uint8 {
	s := make([]uint8, 81)
	n := 0
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			s[n] = m[i][j]
			n++
		}
	}
	return s
}

// down <--> top
func TransFlip(raw string) string {
	s := padding(raw)
	m := sliceToMatrix(s)
	for j := 0; j < 9; j++ {
		for i := 0; i < 4; i++ {
			m[i][j], m[8-i][j] = m[8-i][j], m[i][j]
		}
	}
	s = matrixToSlice(m)
	return string(s)
}

// left <--> right
func TransMirror(raw string) string {
	s := padding(raw)
	m := sliceToMatrix(s)
	for i := 0; i < 9; i++ {
		for j := 0; j < 4; j++ {
			m[i][j], m[i][8-j] = m[i][8-j], m[i][j]
		}
	}
	s = matrixToSlice(m)
	return string(s)
}

// rotate 90 degrees clockwise
func TransRotate(raw string) string {
	s := padding(raw)
	m := sliceToMatrix(s)
	temp := [9][9]uint8{}
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			temp[j][9-i-1] = m[i][j]
		}
	}
	s = matrixToSlice(temp)
	return string(s)
}

func TransPretty(s string) string {
	in := padding(s)
	out := make([]uint8, 0, 110)

	n := 0
	for i := 0; i < 9; i++ {
		for j := 0; j < 3; j++ {
			out = append(out, in[n:n+3]...)
			if j < 2 {
				out = append(out, ' ')
			} else {
				out = append(out, '\n')
			}
			n += 3
		}
		if (i+1)%3 == 0 && i < 8 {
			out = append(out, '\n')
		}
	}

	return string(out)
}
